package com.tomecode.tools.maven.settings.gui.tabs;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel;

import com.tomecode.tools.maven.settings.gui.Desktop;
import com.tomecode.tools.maven.settings.gui.FrmLoading;
import com.tomecode.tools.maven.settings.model.Mirror;
import com.tomecode.tools.maven.settings.model.Settings;
import com.tomecode.tools.maven.settings.util.URLTester;
import com.tomecode.util.gui.HideNotifiListener;
import com.tomecode.util.gui.PanelFactory;
import com.tomecode.util.gui.component.Button;

/**
 * Tab for edit {@link Mirror}
 * 
 * @author Frastia Tomas
 */
public final class MirrorsTab extends JPanel {

	private static final long serialVersionUID = 7759449222261376093L;

	private final JTable mirrorTable;
	private final ServerTableModel mirrorTableModel;

	private final JPanel editorPanel;

	private final JTextField txtId;
	private final JTextField txtName;
	private final JTextField txtMirrorOf;
	private final JTextField txtUrl;

	private final Button bDelete;
	private final Button bEdit;
	private final Button bSave;
	private final Button bTestUrl;

	private final JLabel labError;

	public MirrorsTab(Settings settings) {
		super(new BorderLayout());
		setBorder(new EmptyBorder(10, 10, 0, 10));
		mirrorTableModel = new ServerTableModel(settings);
		mirrorTable = new JTable(mirrorTableModel);

		labError = new JLabel(" ");
		labError.setForeground(Color.red);

		mirrorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		mirrorTable.setAutoscrolls(true);

		bDelete = new Button("Delete", false, new ActionListener() {
			public final void actionPerformed(ActionEvent e) {
				if (mirrorTable.getSelectedRow() == -1) {
					return;
				}
				mirrorTableModel.remove(mirrorTable.getSelectedRow());
				cleanTxts();
			}
		});
		bEdit = new Button("Edit", false, new ActionListener() {
			public final void actionPerformed(ActionEvent e) {
				if (mirrorTable.getSelectedRow() == -1) {
					return;
				}
				mirrorTableModel.update(mirrorTable.getSelectedRow(), txtId.getText(), txtName.getText(), txtUrl.getText(), txtMirrorOf.getText());
				cleanTxts();
			}
		});
		bSave = new Button("Save", false, new ActionListener() {
			public final void actionPerformed(ActionEvent e) {
				mirrorTableModel.add(txtId.getText(), txtName.getText(), txtUrl.getText(), txtMirrorOf.getText());
				cleanTxts();
			}
		});

		// JPanel pWrapTab = PanelFactory.createBorderLayou();
		// pWrapTab.add(new JScrollPane(mirrorTable), BorderLayout.CENTER);
		// pWrapTab.setPreferredSize(new Dimension(100, 100));
		// add(pWrapTab, BorderLayout.NORTH);

		add(new JScrollPane(mirrorTable), BorderLayout.CENTER);

		txtId = new JTextField();
		txtId.addKeyListener(new KeyAdapter() {
			public final void keyReleased(KeyEvent e) {
				checkIfMirrorExists();
			}
		});
		txtName = new JTextField();
		txtMirrorOf = new JTextField();
		// test url
		bTestUrl = new Button("...", false, new ActionListener() {
			public final void actionPerformed(ActionEvent e) {
				new Thread(new Runnable() {
					public void run() {
						FrmLoading frmLoading = new FrmLoading("Connection url test...");
						try {
							final URLTester tester = new URLTester(new URL(txtUrl.getText()));
							frmLoading.showFrm(new HideNotifiListener() {
								public final void hideForm(Object returnObj) {
									tester.cancel();
									return;
								}
							});

							tester.testConnection(URLTester.TIME_OUT_SECONDS);
							frmLoading.hideMe();
						} catch (ConnectException ex) {
							frmLoading.hideMe();
							JOptionPane.showMessageDialog(Desktop.getComponent(), ex.getMessage() + " url:" + txtUrl.getText(), "Connection error", JOptionPane.ERROR_MESSAGE);
						} catch (MalformedURLException ex) {
							frmLoading.hideMe();
							JOptionPane.showMessageDialog(Desktop.getComponent(), ex.getMessage() + " url:" + txtUrl.getText(), "Url error", JOptionPane.ERROR_MESSAGE);
						}
					}
				}).start();
			}
		});
		bTestUrl.setPreferredSize(new Dimension(20, 19));

		txtUrl = new JTextField();
		txtUrl.addKeyListener(new KeyAdapter() {
			public final void keyReleased(KeyEvent e) {
				validateUrl();
			}
		});

		editorPanel = PanelFactory.createBorderLayout("Server");
		JPanel pFields = PanelFactory.createGridLayout(4, 1);
		editorPanel.add(pFields, BorderLayout.CENTER);
		pFields.add(PanelFactory.wrapWithLabelNorm("Id:", txtId, 48));
		pFields.add(PanelFactory.wrapWithLabelNorm("Name:", txtName, 25));

		JPanel pButtonUrlTest = PanelFactory.createBorderLayout(0, 0, 0, 1);
		pButtonUrlTest.add(PanelFactory.wrapWithLabelNorm("Url:", txtUrl, 42), BorderLayout.CENTER);
		pButtonUrlTest.add(PanelFactory.wrapByBorderLayout(bTestUrl, BorderLayout.NORTH), BorderLayout.EAST);
		pFields.add(pButtonUrlTest);
		pFields.add(PanelFactory.wrapWithLabelNorm("MirrorOf:", txtMirrorOf, 10));

		JPanel pSouth = PanelFactory.createBorderLayout(0, 0, 0, 0);
		pSouth.add(PanelFactory.createButtonsPanel(0, 0, 0, -4, bSave, bEdit, bDelete), BorderLayout.EAST);
		pSouth.add(labError, BorderLayout.CENTER);
		editorPanel.add(pSouth, BorderLayout.SOUTH);

		add(editorPanel, BorderLayout.SOUTH);

		mirrorTable.addKeyListener(new KeyAdapter() {
			public final void keyReleased(KeyEvent e) {
				selectInTable(mirrorTable.getSelectedRow());
			}

		});

		mirrorTable.addMouseListener(new MouseAdapter() {
			public final void mouseClicked(MouseEvent e) {
				selectInTable(mirrorTable.getSelectedRow());
			}
		});

	}

	private final void checkIfMirrorExists() {
		if (txtId.getText().trim().length() == 0) {
			labError.setText("Mirror id cannot be empty");
			bSave.setEnabled(false);
			bEdit.setEnabled(false);
		} else if (mirrorTableModel.exists(txtId.getText())) {
			labError.setText("Mirror id already exists");
			bSave.setEnabled(false);
		} else {
			labError.setText(" ");
			bSave.setEnabled(true);
			bEdit.setEnabled(mirrorTable.getSelectedRow() != -1);
		}
	}

	/**
	 * validate url
	 * 
	 */
	private final void validateUrl() {
		if (txtUrl.getText().trim().length() == 0) {
			bTestUrl.setEnabled(false);
		} else {
			try {
				new URL(txtUrl.getText());
				bTestUrl.setEnabled(true);
			} catch (MalformedURLException e1) {
				bTestUrl.setEnabled(false);
			}
		}

	}

	private final void selectInTable(int selectedRow) {
		if (selectedRow == -1) {
			cleanTxts();
			return;
		}
		Mirror mirror = mirrorTableModel.get(selectedRow);
		txtId.setText(mirror.getId());
		txtUrl.setText(mirror.getUrl());
		txtMirrorOf.setText(mirror.getMirrorOf());
		txtName.setText(mirror.getName());
		validateUrl();
		bDelete.setEnabled(true);
		bEdit.setEnabled(true);
		bSave.setEnabled(true);
		checkIfMirrorExists();
	}

	private final void cleanTxts() {
		txtId.setText("");
		txtUrl.setText("");
		txtMirrorOf.setText("");
		txtName.setText("");
		bDelete.setEnabled(false);
		bEdit.setEnabled(false);
		bSave.setEnabled(false);
		labError.setText(" ");
	}

	/**
	 * 
	 * @author Frastia Tomas
	 * 
	 */
	private final class ServerTableModel extends AbstractTableModel {

		private static final long serialVersionUID = 3479286243525778842L;

		private final String[] columns = new String[] { "Id", "Name", "url", "mirrorOr" };

		private final Settings settings;

		private ServerTableModel(Settings settings) {
			this.settings = settings;
		}

		private final boolean exists(String id) {
			return settings.existsMirror(id);
		}

		private final Mirror get(int selectedRow) {
			return settings.getMirrors().get(selectedRow);
		}

		private final void add(String id, String name, String url, String mirrorOf) {
			Mirror mirror = new Mirror();
			mirror.setId(id);
			mirror.setName(name);
			mirror.setUrl(url);
			mirror.setMirrorOf(mirrorOf);
			settings.addMirror(mirror);
			fireTableStructureChanged();
		}

		private final void update(int selectedRow, String id, String name, String url, String mirrorOf) {
			Mirror mirror = settings.getMirrors().get(selectedRow);
			mirror.setId(id);
			mirror.setName(name);
			mirror.setUrl(url);
			mirror.setMirrorOf(mirrorOf);
			fireTableDataChanged();
		}

		public final void remove(int selectedRow) {
			settings.getMirrors().remove(selectedRow);
			fireTableDataChanged();
		}

		public final int getColumnCount() {
			return columns.length;
		}

		public final int getRowCount() {
			return this.settings.getMirrors().size();
		}

		public final String getColumnName(int column) {
			return columns[column];
		}

		public final Object getValueAt(int rowIndex, int columnIndex) {
			Mirror mirror = this.settings.getMirrors().get(rowIndex);
			if (columnIndex == 0) {
				return mirror.getId();
			} else if (columnIndex == 1) {
				return mirror.getName();
			} else if (columnIndex == 2) {
				return mirror.getUrl();
			}

			return mirror.getMirrorOf();
		}

	}
}
